package gameLogic;

public class Observer implements EventHandler {
	// rows, columns, and diagonal status flags
	// -1 = blocked
	// 0 = empty
	// 1 = p1 has an X in the row
	// 11 = p1 has 2 X in the row
	// 111 = p1 has 3 X in the row
	// 2 = p2 has 1inR
	// 22 = p2 has 2inR
	// 222 = p2 has 3inR
	int column[];
	int row[];
	int forwardDiagonal;
	int backwardDiagonal;

	// 0 = game in progress
	// 111 = p1 wins
	// 222 = p2 wins
	int gameResult;

	Observer() {
		column = new int[3];
		row = new int[3];
		clear();
	}

	// assuming move is on an empty spot in the Row/Column/Diagonal
	int updateRowStatus(int oldStatus, Move move, Boolean updateGameResult) {
		switch (oldStatus) {
		case 0:
			if (move.v == BoardState.X) {
				if (updateGameResult)
					Move.xIconType = 1;
				return 1;
			} else {
				if (updateGameResult)
					Move.yIconType = 4;
				return 2;
			}
		case 1:
			if (move.v == BoardState.X) {
				if (updateGameResult)
					Move.xIconType = 2;
				return 11;
			} else
				return -1;
		case 11:
			if (move.v == BoardState.X) {
				if (updateGameResult) {
					gameResult = 111;
					Move.xIconType = 3;
				}
				return 111;
			} else
				return -1;
		case 2:
			if (move.v == BoardState.O) {
				if (updateGameResult)
					Move.yIconType = 5;
				return 22;
			} else
				return -1;
		case 22:
			if (move.v == BoardState.O) {
				if (updateGameResult) {
					gameResult = 222;
					Move.yIconType = 6;
				}
				return 222;
			} else
				return -1;
		default:
			return oldStatus;
		}
	}

	void updateStatus(Move move) {
		column[move.x] = updateRowStatus(column[move.x], move, true);
		row[move.y] = updateRowStatus(row[move.y], move, true);
		if (isInBackwardDiagonal(move))
			backwardDiagonal = updateRowStatus(backwardDiagonal, move, true);
		if (isInForwardDiagonal(move))
			forwardDiagonal = updateRowStatus(forwardDiagonal, move, true);
	}

	int getMoveEffect(Move move, int target) {
		int effect = 0;
		if (updateRowStatus(column[move.x], move, false) == target)
			effect++;
		if (updateRowStatus(row[move.y], move, false) == target)
			effect++;
		if (isInBackwardDiagonal(move)
				&& updateRowStatus(backwardDiagonal, move, false) == target)
			effect++;
		if (isInForwardDiagonal(move)
				&& updateRowStatus(forwardDiagonal, move, false) == target)
			effect++;
		return effect;
	}

	static boolean isInBackwardDiagonal(Move move) {
		return (move.x == move.y) ? true : false;
	}

	static boolean isInForwardDiagonal(Move move) {
		return ((move.x == 0 && move.y == 2) || (move.x == 1 && move.y == 1) || (move.x == 2 && move.y == 0)) ? true
				: false;
	}

	void clear() {
		for (int i = 0; i < 3; i++) {
			column[i] = 0;
			row[i] = 0;
		}
		forwardDiagonal = 0;
		backwardDiagonal = 0;
		gameResult = 0;
	}

	// handles move-made event generated by board
	@Override
	public void actionPerformed(Object args) {
		updateStatus((Move) args);
	}
}
